﻿// <copyright file="ListViewer.cs" company="Tullow Oil PLC">Copyright © Tullow Oil PLC 2012</copyright>

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Xml;
using Microsoft.SharePoint;

namespace Webtechy.SharePoint.Utilities.ListViewer
{
    /// <summary>
    /// List Viewer class.
    /// </summary>
    /// <remarks></remarks>
    public partial class ListViewer : Form
    {
        /// <summary>
        /// Initializes a new instance of the <see cref="T:Webtechy.SharePoint.Utilities.ListViewer.ListViewer">ListViewer</see> class. 
        /// </summary>
        /// <remarks></remarks>
        public ListViewer()
        {
            this.InitializeComponent();
        }

        /// <summary>
        /// This method was found on the Internet (see link below) to format the text correctly as XML.
        /// </summary>
        /// <param name="xml">The XML string.</param>
        /// <seealso cref="http://www.knowdotnet.com/articles/indentxml.html">Easy Way to Indent XML in a TextBox</seealso>
        /// <returns>An XML string that is tabulated.</returns>
        /// <remarks></remarks>
        private static string IndentXMLString(string xml)
        {
            string outXml = string.Empty;
            MemoryStream ms = new MemoryStream();

            // Create a XMLTextWriter that will send its output to a memory stream (file)
            XmlTextWriter xtw = new XmlTextWriter(ms, Encoding.Unicode);
            XmlDocument doc = new XmlDocument();

            try
            {
                // Load the unformatted XML text string into an instance of the XML Document Object Model (DOM)
                doc.LoadXml(xml);

                // Set the formatting property of the XML Text Writer to indented the text writer is where the indenting will be performed
                xtw.Formatting = Formatting.Indented;

                // Write dom xml to the xmltextwriter
                doc.WriteContentTo(xtw);

                // Flush the contents of the text writer to the memory stream, which is simply a memory file
                xtw.Flush();

                // Set to start of the memory stream (file)
                ms.Seek(0, SeekOrigin.Begin);

                // Create a reader to read the contents of the memory stream (file)
                StreamReader sr = new StreamReader(ms);

                // Return the formatted string to caller
                return sr.ReadToEnd();
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
                return string.Empty;
            }
        }

        /// <summary>
        /// This method is called when you get the SPSite.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">An <see cref="T:System.EventArgs">EventArgs</see> that contains the event data.</param>
        /// <remarks></remarks>
        private void btnGet_Click(object sender, EventArgs e)
        {
            try
            {
                using (SPSite site = new SPSite(this.tbSiteURL.Text))
                {
                    this.PopulateWebs(site);
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        }

        /// <summary>
        /// This method populates the combo box with the various SPWebs.
        /// </summary>
        /// <param name="site">The SPSite object to get the webs for.</param>
        /// <remarks></remarks>
        private void PopulateWebs(SPSite site)
        {
            try
            {
                cbWebs.Items.Clear();
                cbWebs.Enabled = true;
                foreach (SPWeb web in site.AllWebs)
                {
                    cbWebs.Items.Insert(0, web.ServerRelativeUrl);
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        }

        /// <summary>
        /// This method populates the combo box with the various SPLists.
        /// </summary>
        /// <param name="web">The SPWeb object to get the lists for.</param>
        /// <remarks></remarks>
        private void PopulateLists(SPWeb web)
        {
            try
            {
                this.cbLists.Items.Clear();
                this.cbLists.Enabled = true;
                foreach (SPList list in web.Lists)
                {
                    if (list.Title != string.Empty)
                    {
                        this.cbLists.Items.Insert(0, list.Title);
                    }
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        }

        /// <summary>
        /// This method populates the combo box with the various SPViews.
        /// </summary>
        /// <param name="list">The SPList object of the list to get the views for.</param>
        /// <remarks></remarks>
        private void PopulateViews(SPList list)
        {
            try
            {
                this.cbViews.Items.Clear();
                this.cbViews.Enabled = true;
                foreach (SPView view in list.Views)
                {
                    if (view.Title != string.Empty)
                    {
                        this.cbViews.Items.Insert(0, view.Title);
                    }
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        }

        /// <summary>
        /// This method is called when the SPWebs combo box is changed.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">An <see cref="T:System.EventArgs">EventArgs</see> that contains the event data.</param>
        /// <remarks></remarks>
        private void cbWebs_SelectedIndexChanged(object sender, EventArgs e)
        {
            try
            {
                using (SPSite site = new SPSite(this.tbSiteURL.Text))
                {
                    string webName = this.cbWebs.SelectedItem.ToString();
                    using (SPWeb web = site.AllWebs[webName])
                    {
                        this.PopulateLists(web);
                        ////tbDefinition.Text = web.
                    }
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        }

        /// <summary>
        /// This method is called when the SPLists combo box is changed.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">An <see cref="T:System.EventArgs">EventArgs</see> that contains the event data.</param>
        /// <remarks></remarks>
        private void cbLists_SelectedIndexChanged(object sender, EventArgs e)
        {
            try
            {
                using (SPSite site = new SPSite(this.tbSiteURL.Text))
                {
                    string webName = this.cbWebs.SelectedItem.ToString();
                    using (SPWeb web = site.AllWebs[webName])
                    {
                        string listName = this.cbLists.SelectedItem.ToString();
                        SPList list = web.Lists[listName];
                        this.PopulateViews(list);
                        this.tbDefinition.Text = IndentXMLString(list.SchemaXml);
                    }
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        }

        /// <summary>
        /// This method is called when the SPViews combo box is changed.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">An <see cref="T:System.EventArgs">EventArgs</see> that contains the event data.</param>
        /// <remarks></remarks>
        private void cbViews_SelectedIndexChanged(object sender, EventArgs e)
        {
            try
            {
                using (SPSite site = new SPSite(this.tbSiteURL.Text))
                {
                    string webName = this.cbWebs.SelectedItem.ToString();
                    using (SPWeb web = site.AllWebs[webName])
                    {
                        string listName = this.cbLists.SelectedItem.ToString();
                        SPList list = web.Lists[listName];
                        string viewName = this.cbViews.SelectedItem.ToString();
                        SPView view = list.Views[viewName];
                        this.tbDefinition.Text = IndentXMLString(view.GetViewXml());
                    }
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        }

        /// <summary>
        /// This method is called when the "Copy" button is pressed. It copies the content to the clipboard.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">An <see cref="T:System.EventArgs">EventArgs</see> that contains the event data.</param>
        /// <remarks></remarks>
        private void btnCopy_Click(object sender, EventArgs e)
        {
            try
            {
                Clipboard.SetText(this.tbDefinition.Text);
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        }

        /// <summary>
        /// This method is called when the "Close" button is pressed. It closes the form.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">An <see cref="T:System.EventArgs">EventArgs</see> that contains the event data.</param>
        /// <remarks></remarks>
        private void btnClose_Click(object sender, EventArgs e)
        {
            try
            {
                this.Close();
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        }
    }
}
